<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <script>
    window.onload = function () {
      var lockReconnect = false;
      var wsCreateHandler;
      var wsObj;

      createWebSocket();


      function createWebSocket() {
        try {
          wsObj = new WebSocket("ws://localhost:2333");
          initWsEventHandle();
        } catch (e) {
          console.log("创建异常", e);
          reconnect();
        }
      }

      function initWsEventHandle() {
        try {
          wsObj.onopen = function (ev) {
            heartCheck.start();
          }
          wsObj.onmessage = function (ev) {
            heartCheck.start();
          }
          wsObj.onclose = function (ev) {
            console.log("onclose")
            reconnect();
          }
          wsObj.onerror = function (ev) {
            console.log("onerror")
            reconnect()
          }
        } catch (e) {
          console.log("事件初始化绑定err", e)
          reconnect()
        }
      }

      //重连
      function reconnect() {
        if (lockReconnect) return;
        console.log("1秒后重连");
        lockReconnect = true;
        wsCreateHandler && clearTimeout(wsCreateHandler);
        wsCreateHandler = setTimeout(function () {
          console.log("重连开始");
          createWebSocket();
          lockReconnect = false;
          console.log("重连完成");
        }, 1000)
      }
    }



    //第一种
    var heartCheck = {
      timeout: 15000,
      timeoutObj: null,
      serverTimeoutObj: null,
      //重置
      reset: function () {
        cleartimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        this.start();
      },
      //开启定时器
      start: function () {
        var self = this;
        this.timeoutObj && clearTimeout(this.timeoutObj);
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
        this.timeoutObj = setTimeout(function () {
          console.log("发送ping到后台");
          try {
            wsObj.send("ping");
          } catch (e) {
            conosle.log('发送到后台异常');
          }
          //内嵌计时器
          self.serverTimeoutObj = setTimeout(function () {
            console.log("没有收到后台数据，关闭连接");
            reconnect(); //重连
          }, self.timeout)
        }, this.timeout)
      }
    }

    //第二种
    function connectSocket() {
      let ws = new WebSocket(url);
      ws.onopen = function () {
        ws.onmessage = function (e) {
          let data = JSON.parse(e.data);
          console.log(data);
          // data.type 中是前后端约定的类型，我们这里"ping"是心跳
          if (data.type === 'ping') {
            clearInterval(interval);

            // 如果一定时间没有调用clearInterval，则执行重连
            interval = setInterval(function () {
              connectSocket();
            }, 60000);
          }
          if (data.type && data.type !== 'ping') { // 消息推送
            // code ...
          }
        };
      }
    }
  </script>
</body>

</html>